package cn.tedu.aiumall.order.webapi.filter;

import cn.tedu.aiumall.common.restful.JsonResult;
import cn.tedu.aiumall.common.restful.ResponseCode;
import cn.tedu.aiumall.order.webapi.security.LoginPrincipal;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

@Component
@Slf4j
public class JwtAuthorizationFilter extends OncePerRequestFilter {

    @Value("fg1dasfa6e5g165ADSGFSADG5sfaf")
    private String secureKey;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        log.info("过滤器开始执行...");
        //清除SecurityContext原有的认证信息
        //避免曾经成功访问过，后续不携带jwt也视为”已认证“
        SecurityContextHolder.clearContext();
        String jwt=request.getHeader("Authorization");
        log.info("尝试从请求头中获取JWT数据：{}",jwt);
        if (!StringUtils.hasText(jwt) || jwt.length()<113){
            log.info("获取jwt的值视为无效，直接放行...");
            filterChain.doFilter(request,response);
            return;
        }

        Claims claims= null;
        response.setContentType("application/json;charset=utf-8");

        try {
            claims = Jwts.parser().setSigningKey(secureKey).
                    parseClaimsJws(jwt).getBody();
        }catch (ExpiredJwtException e){
            String message="登录信息已过期，请重新登录!";
            JsonResult<Void> jsonResult=JsonResult.failed(ResponseCode.ERR_JWT_PARSE,message);
            String jsonString=JSON.toJSONString(jsonResult);
            PrintWriter writer = response.getWriter();
            writer.println(jsonString);
            writer.close();
            return;
        }catch (SignatureException e) {
            log.info("解析JWT失败：{}：{}", e.getClass().getName(), e.getMessage());
            String message = "无法获取到有效的登录信息，请重新登录！";
            JsonResult<Void> jsonResult = JsonResult.failed(ResponseCode.ERR_JWT_PARSE, message);
            String jsonString = JSON.toJSONString(jsonResult);
            PrintWriter writer = response.getWriter();
            writer.println(jsonString);
            writer.close();
            return;
        } catch (MalformedJwtException e) {
            log.info("解析JWT失败：{}：{}", e.getClass().getName(), e.getMessage());
            String message = "无法获取到有效的登录信息，请重新登录！";
            JsonResult<Void> jsonResult = JsonResult.failed(ResponseCode.ERR_JWT_PARSE, message);
            String jsonString = JSON.toJSONString(jsonResult);
            PrintWriter writer = response.getWriter();
            writer.println(jsonString);
            writer.close();
            return;
        } catch (Throwable e) {
            log.info("解析JWT失败：{}：{}", e.getClass().getName(), e.getMessage());
            String message = "无法获取到有效的登录信息，请重新登录！";
            JsonResult<Void> jsonResult = JsonResult.failed(ResponseCode.ERR_JWT_PARSE, message);
            String jsonString = JSON.toJSONString(jsonResult);
            PrintWriter writer = response.getWriter();
            writer.println(jsonString);
            writer.close();
            e.printStackTrace();
            return;
        }

        Long id=claims.get("id",Long.class);
        log.info("从JWT中解析到【id】的值：{}",id);
        String username=claims.get("username",String.class);
        log.info("从JWT中解析到【username】的值：{}",username);
        String authorityListString = claims.get("authorities", String.class);
        log.info("从JWT中解析得到【authorities】的值：{}", authorityListString);

        //准备权限，将封装到认证信息中
        List<SimpleGrantedAuthority> authorityList =
                JSON.parseArray(authorityListString,SimpleGrantedAuthority.class);
        //创建自定义的当事人类型的对象
        LoginPrincipal loginPrincipal=new LoginPrincipal();
        loginPrincipal.setId(id);
        loginPrincipal.setUsername(username);
        Authentication authentication =
                new UsernamePasswordAuthenticationToken
                        (loginPrincipal, null, authorityList);
        //将认证信息存放到SecurityContext中
        SecurityContext securityContext= SecurityContextHolder.getContext();
        securityContext.setAuthentication(authentication);


        log.info("过滤器执行放行...");
        filterChain.doFilter(request,response);





    }
}
